package com.yao2san.sim.storage.client.core.integrate;

import com.aliyun.oss.OSS;
import com.qcloud.cos.COSClient;
import com.yao2san.sim.storage.client.config.*;
import com.yao2san.sim.storage.client.core.downloader.*;
import com.yao2san.sim.storage.client.core.enums.StorageType;
import com.yao2san.sim.storage.client.exception.StorageInstanceNotFoundException;
import com.yao2san.sim.storage.client.util.StorageUtil;
import io.minio.MinioClient;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ServiceLoader;

import static com.yao2san.sim.storage.client.core.enums.StorageType.*;
import static com.yao2san.sim.storage.client.core.integrate.IntegrateAdapterUtil.getClient;
import static com.yao2san.sim.storage.client.core.integrate.IntegrateAdapterUtil.getProperties;

/**
 * @author wxg
 **/
public class IntegrateDownloader extends AbstractIntegrateDownloader {
    private final SimStorageClientProperties clientProperties;
    private final IntegrateConfig integrateConfig;

    private final Downloader downloader;

    public IntegrateDownloader(SimStorageClientProperties clientProperties, IntegrateConfig integrateConfig) {
        this.clientProperties = clientProperties;
        this.integrateConfig = integrateConfig;
        this.downloader = getDownloader();
    }

    @Override
    public void download(String object, OutputStream out) throws IOException {
        StorageUtil.checkObjectName(object);
        downloader.download(object, out);
    }

    private Downloader getDownloader() {
        Downloader downloader = null;
        StorageType storageType = integrateConfig.getStorageType();
        if (storageType.equals(LOCAL)) {
            downloader = new LocalDownloader((LocalProperties) getProperties(integrateConfig));
        }
        if (storageType.equals(FTP)) {
            //TODO
        }
        if (storageType.equals(MINIO)) {
            downloader = new MinioDownloader((MinioClient) getClient(integrateConfig), (MinioProperties) getProperties(integrateConfig));
        }
        if (storageType.equals(ALI_OSS)) {
            downloader = new AliOssDownloader((OSS) getClient(integrateConfig), (AliOssProperties) getProperties(integrateConfig));
        }
        if (storageType.equals(TENCENT_COS)) {
            downloader = new TencentCosDownloader((COSClient) getClient(integrateConfig), (TencentCosProperties) getProperties(integrateConfig));
        }
        if (storageType.equals(QI_NIU)) {
            //TODO
        }

        //custom storage type with spi
        if (storageType.equals(CUSTOM)) {
            String customType = clientProperties.getCustomType();
            if (customType == null || customType.isEmpty()) {
                throw new IllegalArgumentException("Custom type can not be empty, please check your config");
            }
            ServiceLoader<Downloader> serviceLoader = ServiceLoader.load(Downloader.class);
            for (Downloader service : serviceLoader) {
                if (customType.equalsIgnoreCase(service.getName())) {
                    downloader = service;
                    break;
                }
            }
            if (downloader == null) {
                throw new StorageInstanceNotFoundException("Custom downloader not found:" + customType + ", please check your config");
            }
        }

        if (downloader == null) {
            throw new StorageInstanceNotFoundException(integrateConfig.getStorageType().name());
        }
        return downloader;
    }


    @Override
    public String url(String object) {
        return url(object, false);
    }

    @Override
    public String url(String object, boolean preSigned) {
        if (preSigned) {
            return getDownloader().url(object);
        } else {
            return getDownloader().url(object, true);
        }
    }

    @Override
    public String getName() {
        return INTEGRATE.name();
    }
}
